
#ifndef _KEYBOARD_H_
#define _KEYBOARD_H_

#include "keyboard_win32.h"
#include "keyboard_wii.h"
#include "keyboard_sdl.h"
#include <string>
#include <vector>

namespace input
{
class KeyboardListener;

// abstract Keyboard class.
class	Keyboard
{
public:
	static const int		BUFFER_SIZE = 512;
	struct	KEY
	{
		// test the key
		inline bool			IsKeyPressed()  { return KeyChanged && KeyDown; };
		inline bool			IsKeyReleased() { return KeyChanged && !KeyDown; };



		unsigned long		KeyID;
		bool				KeyChanged;		// did it change this frame
		bool				KeyDown;		// is the key down ?
		float				TimeStamp;		// when did it change last time ?
	};

	static Keyboard&		Instance();

	bool					Tick( float time);
	KEY*					GetKey(unsigned int ID);

	// key-testing
	bool					IsKeyDown(unsigned int Key);	
	bool					IsKeyPressed(unsigned int Key);	
	bool					IsKeyReleased(unsigned int Key);	

	// Keyboard events. These can be generated from outside (SDL/Wii) or internally
	void					OnCharReceived(unsigned int Key);
	void					OnCharPressed(unsigned int Key);
	void					OnCharReleased(unsigned int Key);

// listener functions
	void						AddListener(KeyboardListener* _pListener);
	int							GetListenerIndex(KeyboardListener* _pListener);
	void						DropListener(KeyboardListener* _pListener);

	// static helper functions
	static bool					GetClipBoard(std::string& Buffer);
	static bool					SetClipBoard(std::string& Buffer);
	static bool					SetClipBoard(std::wstring& Buffer);
	static bool					IsNumLockOn();
	static bool					IsCtrlDown();
	static bool					IsShiftDown();
	static bool					IsAltDown();
	static bool					IsVKDown(unsigned int VK);		// windows code
private:
	Keyboard()	
	{ 
		Init(); 
	};
	~Keyboard()	{ Shutdown(); };
	void					Init();
	void					Shutdown();


	KEY								m_KeyA[BUFFER_SIZE];
	std::vector<KeyboardListener*>	m_Listeners;


};

class KeyboardListener
{
public:
	/// will automatically register itself with the keyboard handler
						KeyboardListener();
	/// will automatically de-register itself with the keyboard handler
	virtual				~KeyboardListener();
	/// key was pressed this frame
	virtual	void		KeyPressed(Keyboard::KEY* pKey) {};
	/// key was released this frame
	virtual void		KeyReleased(Keyboard::KEY* pKey) {};
	/// Translated character code received
	virtual void		CharReceived(unsigned int Key) {};
	/// key was pressed last frame && this frame. \n
	/// note that you WILL get this message at the same time as KeyPressed
	virtual void		KeyDown(Keyboard::KEY* pKey) {};
	/// key was held down for the time interval defined in RepeatInterval
	/// note that you WILL get this message at the same time as KeyDown
	virtual void		KeyRepeat(Keyboard::KEY* pKey) {};

	void				Disable()	{ m_IsEnabled = false; };
	void				Enable()	{ m_IsEnabled = true; };
	bool				IsEnabled() const { return m_IsEnabled; };
public:
	bool				m_IsEnabled;
	Keyboard*			m_pKeyboard;
};

}  //namespace input

#define GET_KEYBOARD() input::Keyboard::Instance()
#endif // _KEYBOARD_H_